#include "GTriangle3.h"

namespace GMath
{

	GTriangle3::GTriangle3()
	{
	}

	GTriangle3::GTriangle3(const GVector3& ThePoint0, const GVector3& ThePoint1, const GVector3& ThePoint2)
	{
		Point0 = ThePoint0;
		Point1 = ThePoint1;
		Point2 = ThePoint2;
	}

	void GTriangle3::Create(const GVector3& ThePoint0, const GVector3& ThePoint1, const GVector3& ThePoint2)
	{
		Point0 = ThePoint0;
		Point1 = ThePoint1;
		Point2 = ThePoint2;
	}

	float GTriangle3::GetArea() const
	{
		GVector3 Vec1 = Point1 - Point0;
		GVector3 Vec2 = Point2 - Point0;

		GVector3 CrossResult;
		GVector3::Cross(CrossResult, Vec1, Vec2);

		return CrossResult.Lenght() / 2.0f;
	}

	GVector3 GTriangle3::GetCenter() const
	{
		return (Point0 + Point1 + Point2) / 3.0f;
	}

	GVector3 GTriangle3::GetNormal() const
	{
		GVector3 Vec1 = Point1 - Point0;
		GVector3 Vec2 = Point2 - Point0;

		GVector3 Normal;
		GVector3::Cross(Normal, Vec1, Vec2);
		Normal.Normalize();

		return Normal;
	}

	bool GTriangle3::CheckFront(const GVector3& ViewVec, bool TwoSided) const
	{
		GVector3 Normal = GetNormal();

		return TwoSided || (GVector3::Dot(ViewVec, Normal) >= 0.0f);
	}

	GVector3 GTriangle3::GetCoordBarycentric(const GVector3& SurfacePoint) const
	{
		GTriangle3 Triangle0(Point2, Point0, SurfacePoint);
		GTriangle3 Triangle1(Point0, Point1, SurfacePoint);
		GTriangle3 Triangle2(Point1, Point2, SurfacePoint);

		float Area0 = Triangle0.GetArea();
		float Area1 = Triangle1.GetArea();
		float Area2 = Triangle2.GetArea();
		float Total = Area0 + Area1 + Area2;

		return GVector3(Area0, Area1, Area2) / Total;
	}

	GVector3 GTriangle3::GetCoordEuclidean(const GVector3& BarycentricCoord) const
	{
		return	Point0 * BarycentricCoord.x + 
				Point1 * BarycentricCoord.y + 
				Point2 * BarycentricCoord.z;
	}

}